﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace Devonline.Core
{
    public static class EnumExtensions
    {
        /// <summary>
        /// 获取枚举的可显示名字
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string? GetDisplayName<T>(this Enum @enum)
        {
            var type = typeof(T);
            if (!type.IsEnum || @enum is not T)
            {
                return string.Empty;
            }

            var field = type.GetField(@enum.ToString("F"));
            if (field == null)
            {
                return string.Empty;
            }

            var display = field.GetCustomAttribute<DisplayAttribute>();
            if (display != null)
            {
                return display.Name;
            }

            var displayName = field.GetCustomAttribute<DisplayNameAttribute>();
            if (displayName != null)
            {
                return displayName.DisplayName;
            }

            var description = field.GetCustomAttribute<DescriptionAttribute>();
            if (description != null)
            {
                return description.Description;
            }

            return string.Empty;
        }
        /// <summary>
        /// 从枚举的 DisplayName 属性得到当前枚举值
        /// 用于从 excel 文本中反射获取枚举值
        /// </summary>
        /// <param name="type">当前枚举</param>
        /// <param name="value">DisplayName 的值</param>
        /// <returns>枚举值</returns>
        public static T GetEnumValueByDisplayName<T>(this string value) where T : struct, Enum
        {
            var type = typeof(T);
            return Enum.GetValues<T>().FirstOrDefault(x => type.GetDisplayName(x.ToString()) == value);
        }
        /// <summary>
        /// 通过枚举字段获取枚举对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T GetEnumValueByJsonName<T>(this string value) where T : struct, Enum
        {
            var type = typeof(T);
            return Enum.GetValues<T>().FirstOrDefault(x => type.GetJsonPropertyName(x.ToString()) == value);
        }

        /// <summary>
        /// 将枚举转换为枚举值和显示值的键值对的默认形式
        /// 键采用 F 格式, 值采用可显示特性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static ICollection<KeyValuePair<string, string?>> ToKeyValuePairs<T>() where T : struct, Enum => Enum.GetValues<T>().ToDictionary(key => key.ToString("F"), value => value.GetDisplayName<T>());
        /// <summary>
        /// 将枚举转换为键值可定义的键值对
        /// F 格式将显示枚举的字符串表示值
        /// D 格式将显示枚举的数字表示值
        /// 值格式不传值则默认使用可显示特性描述值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static ICollection<KeyValuePair<string, string?>> ToKeyValuePairs<T>(string keyFormat = "F", string? valueFormat = null) where T : struct, Enum => Enum.GetValues<T>().ToDictionary(key => key.ToString(keyFormat), value => string.IsNullOrWhiteSpace(valueFormat) ? value.GetDisplayName<T>() : value.ToString(valueFormat));
    }
}
